// Copyright Epic Games, Inc. All Rights Reserved.

#include "OverrideWidget/WGIInputKeySelector.h"
#include "Engine/Font.h"
#include "UObject/ConstructorHelpers.h"
#include "UObject/FrameworkObjectVersion.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Internationalization/Internationalization.h"




void SWGI_InputKeySelector::Construct(const FArguments& InArgs)
{
	OnResetFocus = InArgs._OnResetFocus;

	SInputKeySelector::Construct(SInputKeySelector::FArguments()
		.SelectedKey(InArgs._SelectedKey)
		.Margin(InArgs._Margin)
		.ButtonStyle(InArgs._ButtonStyle)
		.TextStyle(InArgs._TextStyle)
		.KeySelectionText(InArgs._KeySelectionText)
		.NoKeySpecifiedText(InArgs._NoKeySpecifiedText)
		.AllowModifierKeys(InArgs._AllowModifierKeys)
		.AllowGamepadKeys(InArgs._AllowGamepadKeys)
		.EscapeKeys(InArgs._EscapeKeys)
		.OnKeySelected(InArgs._OnKeySelected)
		.OnIsSelectingKeyChanged(InArgs._OnIsSelectingKeyChanged)
	);
}

FReply SWGI_InputKeySelector::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
	FReply Result = SInputKeySelector::OnKeyUp(MyGeometry, InKeyEvent);
	OnResetFocus.ExecuteIfBound();
	return Result;
}

FReply SWGI_InputKeySelector::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	FReply Result = SInputKeySelector::OnMouseButtonDown(MyGeometry, MouseEvent);
	OnResetFocus.ExecuteIfBound();
	return Result;
}





#define LOCTEXT_NAMESPACE "UMG"

static FButtonStyle* DefaultInputKeySelectorButtonStyle = nullptr;
static FTextBlockStyle* DefaultInputKeySelectorTextStyle = nullptr;

UWGI_InputKeySelector::UWGI_InputKeySelector(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	if (DefaultInputKeySelectorButtonStyle == nullptr)
	{
		// HACK: THIS SHOULD NOT COME FROM CORESTYLE AND SHOULD INSTEAD BE DEFINED BY ENGINE TEXTURES/PROJECT SETTINGS
		DefaultInputKeySelectorButtonStyle = new FButtonStyle(FCoreStyle::Get().GetWidgetStyle<FButtonStyle>("Button"));

		// Unlink UMG default colors from the editor settings colors.
		DefaultInputKeySelectorButtonStyle->UnlinkColors();
	}

	if (DefaultInputKeySelectorTextStyle == nullptr)
	{
		// HACK: THIS SHOULD NOT COME FROM CORESTYLE AND SHOULD INSTEAD BE DEFINED BY ENGINE TEXTURES/PROJECT SETTINGS
		DefaultInputKeySelectorTextStyle = new FTextBlockStyle(FCoreStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText"));

		// Unlink UMG default colors from the editor settings colors.
		DefaultInputKeySelectorTextStyle->UnlinkColors();
	}

	WidgetStyle = *DefaultInputKeySelectorButtonStyle;
	TextStyle = *DefaultInputKeySelectorTextStyle;

	KeySelectionText = NSLOCTEXT("InputKeySelector", "DefaultKeySelectionText", "...");
	NoKeySpecifiedText = NSLOCTEXT("InputKeySelector", "DefaultEmptyText", "Empty");
	SelectedKey = FInputChord(EKeys::Invalid);
	bAllowModifierKeys = true;
	bAllowGamepadKeys = false;

	EscapeKeys.AddUnique(EKeys::Gamepad_Special_Right); // In most (if not all) cases this is going to be the menu button

	if (!IsRunningDedicatedServer())
	{
		static ConstructorHelpers::FObjectFinder<UFont> RobotoFontObj(*UWidget::GetDefaultFontName());
		TextStyle.Font = FSlateFontInfo(RobotoFontObj.Object, 24, FName("Bold"));
	}
}

void UWGI_InputKeySelector::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

	Ar.UsingCustomVersion(FFrameworkObjectVersion::GUID);
}

void UWGI_InputKeySelector::PostLoad()
{
	Super::PostLoad();

	if (GetLinkerCustomVersion(FFrameworkObjectVersion::GUID) < FFrameworkObjectVersion::InputKeySelectorTextStyle)
	{
		TextStyle.Font = Font_DEPRECATED;
		TextStyle.ColorAndOpacity = ColorAndOpacity_DEPRECATED;
	}
}

void UWGI_InputKeySelector::SetSelectedKey(const FInputChord& InSelectedKey)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetSelectedKey(InSelectedKey);
	}
	SelectedKey = InSelectedKey;
}

void UWGI_InputKeySelector::SetKeySelectionText(FText InKeySelectionText)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetKeySelectionText(InKeySelectionText);
	}
	KeySelectionText = MoveTemp(InKeySelectionText);
}

void UWGI_InputKeySelector::SetNoKeySpecifiedText(FText InNoKeySpecifiedText)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetNoKeySpecifiedText(InNoKeySpecifiedText);
	}
	NoKeySpecifiedText = MoveTemp(InNoKeySpecifiedText);
}

void UWGI_InputKeySelector::SetAllowModifierKeys(const bool bInAllowModifierKeys)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetAllowModifierKeys(bInAllowModifierKeys);
	}
	bAllowModifierKeys = bInAllowModifierKeys;
}

void UWGI_InputKeySelector::SetAllowGamepadKeys(const bool bInAllowGamepadKeys)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetAllowGamepadKeys(bInAllowGamepadKeys);
	}
	bAllowGamepadKeys = bInAllowGamepadKeys;
}

bool UWGI_InputKeySelector::GetIsSelectingKey() const
{
	return MyInputKeySelector.IsValid() ? MyInputKeySelector->GetIsSelectingKey() : false;
}

void UWGI_InputKeySelector::SetButtonStyle(const FButtonStyle* InButtonStyle)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetButtonStyle(InButtonStyle);
	}
	WidgetStyle = *InButtonStyle;
}

void UWGI_InputKeySelector::SetEscapeKeys(const TArray<FKey>& InKeys)
{
	if (MyInputKeySelector.IsValid())
	{
		MyInputKeySelector->SetEscapeKeys(InKeys);
	}
	EscapeKeys = InKeys;
}
#if WITH_EDITOR
const FText UWGI_InputKeySelector::GetPaletteCategory()
{
	return LOCTEXT("Advanced", "Advanced");
}
#endif

void UWGI_InputKeySelector::SynchronizeProperties()
{
	Super::SynchronizeProperties();

	MyInputKeySelector->SetSelectedKey(SelectedKey);
	MyInputKeySelector->SetMargin(Margin);
	MyInputKeySelector->SetButtonStyle(&WidgetStyle);
	MyInputKeySelector->SetTextStyle(&TextStyle);
	MyInputKeySelector->SetKeySelectionText(KeySelectionText);
	MyInputKeySelector->SetNoKeySpecifiedText(NoKeySpecifiedText);
	MyInputKeySelector->SetAllowModifierKeys(bAllowModifierKeys);
	MyInputKeySelector->SetAllowGamepadKeys(bAllowGamepadKeys);
	MyInputKeySelector->SetEscapeKeys(EscapeKeys);
}

void UWGI_InputKeySelector::ReleaseSlateResources(bool bReleaseChildren)
{
	Super::ReleaseSlateResources(bReleaseChildren);

	MyInputKeySelector.Reset();
}

TSharedRef<SWidget> UWGI_InputKeySelector::RebuildWidget()
{
	MyInputKeySelector = SNew(SWGI_InputKeySelector)
		.SelectedKey(SelectedKey)
		.Margin(Margin)
		.ButtonStyle(&WidgetStyle)
		.TextStyle(&TextStyle)
		.KeySelectionText(KeySelectionText)
		.NoKeySpecifiedText(NoKeySpecifiedText)
		.AllowModifierKeys(bAllowModifierKeys)
		.AllowGamepadKeys(bAllowGamepadKeys)
		.EscapeKeys(EscapeKeys)
		.OnKeySelected(BIND_UOBJECT_DELEGATE(SInputKeySelector::FOnKeySelected, HandleKeySelected))
		.OnIsSelectingKeyChanged(BIND_UOBJECT_DELEGATE(SInputKeySelector::FOnIsSelectingKeyChanged, HandleIsSelectingKeyChanged))
		.OnResetFocus_UObject(this, &UWGI_InputKeySelector::SlateHandleResetFocus);
	return MyInputKeySelector.ToSharedRef();
}

void UWGI_InputKeySelector::HandleKeySelected(const FInputChord& InSelectedKey)
{
	SelectedKey = InSelectedKey;
	OnKeySelected.Broadcast(SelectedKey);
}

void UWGI_InputKeySelector::HandleIsSelectingKeyChanged()
{
	OnIsSelectingKeyChanged.Broadcast();
}

void UWGI_InputKeySelector::SetTextBlockVisibility(const ESlateVisibility InVisibility)
{
	if (MyInputKeySelector.IsValid())
	{
		EVisibility SlateVisibility = UWidget::ConvertSerializedVisibilityToRuntime(InVisibility);
		MyInputKeySelector->SetTextBlockVisibility(SlateVisibility);
	}
}

void UWGI_InputKeySelector::SlateHandleResetFocus()
{
	OnResetFocus.ExecuteIfBound();
}

#undef LOCTEXT_NAMESPACE
